package com.gitee.wsl.compose.ui.richtext.edit.state

import androidx.compose.ui.text.SpanStyle
import com.gitee.wsl.compose.ext.text.customMerge
import com.gitee.wsl.compose.ext.text.isSpecifiedFieldsEquals
import com.gitee.wsl.compose.ext.text.unmerge

/**
 * Toggle the [SpanStyle]
 * If the passed span style doesn't exist in the [currentSpanStyle] it's going to be added.
 * If the passed span style already exists in the [currentSpanStyle] it's going to be removed.
 *
 * Example: You can toggle Bold FontWeight by passing:
 *
 * ```
 * SpanStyle(fontWeight = FontWeight.Bold)
 * ```
 *
 * @param spanStyle the span style that is going to be toggled.
 * Only the specified params are going to be toggled, and the non specified ones are going to be ignored.
 * @see [addSpanStyle]
 * @see [removeSpanStyle]
 */
fun RichTextState.toggleSpanStyle(spanStyle: SpanStyle) {
    if (currentSpanStyle.isSpecifiedFieldsEquals(spanStyle))
        removeSpanStyle(spanStyle)
    else
        addSpanStyle(spanStyle)
}

/**
 * Add new [SpanStyle] to the [currentSpanStyle]
 *
 * Example: You can add Bold FontWeight by passing:
 *
 * ```
 * SpanStyle(fontWeight = FontWeight.Bold)
 * ```
 *
 * @param spanStyle the span style that is going to be added to the [currentSpanStyle].
 * Only the specified params are going to be applied, and the non specified ones are going to be ignored.
 * @see [removeSpanStyle]
 * @see [toggleSpanStyle]
 */
fun RichTextState.addSpanStyle(spanStyle: SpanStyle) {
    if (!currentSpanStyle.isSpecifiedFieldsEquals(spanStyle)) {
        toAddSpanStyle = toAddSpanStyle.customMerge(spanStyle)
        toRemoveSpanStyle = toRemoveSpanStyle.unmerge(spanStyle)
    }

    if (!selection.collapsed)
        applyRichSpanStyleToSelectedText()
}

/**
 * Remove an existing [SpanStyle] from the [currentSpanStyle]
 *
 * Example: You can remove Bold FontWeight by passing:
 *
 * ```
 * SpanStyle(fontWeight = FontWeight.Bold)
 * ```
 *
 * @param spanStyle the span style that is going to be removed from the [currentSpanStyle].
 * Only the specified params are going to be removed, and the non specified ones are going to be ignored.
 * @see [addSpanStyle]
 * @see [toggleSpanStyle]
 */
fun RichTextState.removeSpanStyle(spanStyle: SpanStyle) {
    if (currentSpanStyle.isSpecifiedFieldsEquals(spanStyle)) {
        toRemoveSpanStyle = toRemoveSpanStyle.customMerge(spanStyle)
        toAddSpanStyle = toAddSpanStyle.unmerge(spanStyle)
    }

    if (!selection.collapsed)
        applyRichSpanStyleToSelectedText()
}